package gang.org.springframework.boot.web.embedded.tomcat;

import gang.org.springframework.boot.web.server.GangShutdown;
import gang.org.springframework.boot.web.server.GangWebServer;
import org.apache.catalina.Container;
import org.apache.catalina.Context;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.Service;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Tomcat;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author：gang.chen
 * @Date：2023/10/12 9:35
 */
public class GangTomcatWebServer implements GangWebServer {

    public final Tomcat tomcat;

    public final boolean autoStart;

    public final Object monitor = new Object();

    public final GangGracefulShutdown gracefulShutdown;

    public static final AtomicInteger containerCounter = new AtomicInteger(-1);
    

    public GangTomcatWebServer(Tomcat tomcat, boolean autoStart, GangShutdown shutdown)
    {
        this.tomcat =tomcat;
        this.autoStart = autoStart;
        this.gracefulShutdown = null;
        
        initialize();
    }

    private void initialize() {

        System.out.println("Tomcat initialized with port(s): " + getPortsDescription(false));

        synchronized (this.monitor)
        {
            try{

                addInstanceIdToEngineName();

                // Context context = findContext(); TODO

                /**
                 * remove service connectors so that protocol binding doesn't happen when the service is start
                 * */
                //context.addLifecycleListener((event) -> { TODO
                    //if (context.equals(event.getSource()) && Lifecycle.START_EVENT.equals(event.getType())) {
                        // Remove service connectors so that protocol binding doesn't
                        // happen when the service is started.
                        // removeServiceConnectors(); TODO
                    //}
                //});
                
                this.tomcat.start();
                
                //rethrowDeferredStartupExceptions TODO
                
                //ContextBindings.bindClassLoader TODO
                
                startDaemonAwaitThread();

            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    private void removeServiceConnectors() {
        for (Service service : this.tomcat.getServer().findServices()) {
            Connector[] connectors = service.findConnectors().clone();
            for (Connector connector : connectors) {
                service.removeConnector(connector);
            }
        }
    }

    private void startDaemonAwaitThread() {

        Thread awaitThread = new Thread("container-" + containerCounter.get()){
            @Override
            public void run() {
                GangTomcatWebServer.this.tomcat.getServer().await();
            }
        };

        awaitThread.setContextClassLoader(getClass().getClassLoader());
        awaitThread.setDaemon(false);
        awaitThread.start();
    }

    private Context findContext() {

        for (Container child : this.tomcat.getHost().findChildren()) {
            if (child instanceof Context) {
                return (Context) child;
            }
        }
        
        return null;
    }

    private void addInstanceIdToEngineName() {

        int instanceId = containerCounter.incrementAndGet();

        if (instanceId > 0) {
            //TODO
        }
    }

    private String getPortsDescription(boolean localPort) {
        StringBuilder ports = new StringBuilder();
        for (Connector connector : this.tomcat.getService().findConnectors()) {
            if (ports.length() != 0) {
                ports.append(' ');
            }
            int port = localPort ? connector.getLocalPort() : connector.getPort();
            ports.append(port).append(" (").append(connector.getScheme()).append(')');
        }
        return ports.toString();
    }
}
